home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 4
/
Apprentice-Release4.iso
/
Languages
/
PowerMacOberon 1.2
/
Source
/
Elems
/
LinkElems.Mod
(
.txt
)
< prev
next >
Wrap
Oberon Text
|
1995-08-22
|
12KB
|
347 lines
Syntax10.Scn.Fnt
StampElems
Alloc
3 Aug 95
Syntax10b.Scn.Fnt
Syntax10m.Scn.Fnt
Syntax10i.Scn.Fnt
MarkElems
Alloc
MODULE LinkElems; (** HM
IMPORT
Files, Fonts, Display, Input, Viewers, Texts, TextFrames, MenuViewers, TextPrinter, Oberon, PopupElems, MarkElems, FoldElems;
CONST
left =2; middle = 1; right = 0;
pixel = LONG(10000);
stdMenu = "System.Close System.Copy System.Grow Edit.Search Edit.Replace Edit.Store ";
Elem* = POINTER TO ElemDesc;
ElemDesc* = RECORD (Texts.ElemDesc)
file*: ARRAY 32 OF CHAR;
key*: LONGINT
END;
FollowMsg* = RECORD (Texts.ElemMsg) f*: Display.Frame END;
Menu* = POINTER TO MenuDesc;
MenuDesc* = RECORD (PopupElems.ElemDesc)
END;
Frame = POINTER TO FrameDesc;
FrameDesc = RECORD (TextFrames.FrameDesc)
e: Elem
END;
searchKey: LONGINT; (*key of mark element searched in FollowLink; used in Check*)
hint: TextFrames.Frame; (*suggests frame to be used for links emanating from a link menu*)
icon, invIcon: Display.Pattern; (* x = 0, y = 3, w = 9, h = 8 *)
w: Texts.Writer;
PROCEDURE^ New* (file: ARRAY OF CHAR; key: LONGINT): Elem;
PROCEDURE
GetSelection (VAR f: TextFrames.Frame);
(* return frame f with the latest text selection*)
VAR v: Viewers.Viewer; f0: Display.Frame; time: LONGINT; x: INTEGER;
BEGIN
x := 0; time := -1; f := NIL;
WHILE x < Display.Width DO
v := Viewers.This(x, 0);
WHILE v.state > 1 DO
f0 := v.dsc;
WHILE f0 # NIL DO
WITH f0: TextFrames.Frame DO
IF f0.hasSel & (f0.time > time) THEN f := f0; time := f.time END
ELSE
END;
f0 := f0.next
END;
v := Viewers.Next(v)
END;
x := x + v.W
END GetSelection;
PROCEDURE
GetFileName (t: Texts.Text; VAR name: ARRAY OF CHAR);
(* return the name of the viewer which contains text t*)
VAR v, V: Viewers.Viewer; f: Display.Frame; s: Texts.Scanner; x: INTEGER;
BEGIN
V := NIL; x := 0;
WHILE x < Display.Width DO
v := Viewers.This(x, 0);
WHILE v.state > 1 DO
f := v.dsc;
WHILE f # NIL DO
IF (f IS TextFrames.Frame) & (f(TextFrames.Frame).text = t) THEN V := v END;
f := f.next
END;
v := Viewers.Next(v)
END;
x := x + v.W
END;
IF V # NIL THEN
Texts.OpenScanner(s, V.dsc(TextFrames.Frame).text, 0); Texts.Scan(s);
IF s.class IN {Texts.Name, Texts.String} THEN COPY(s.s, name) ELSE name[0] := 0X END
END GetFileName;
PROCEDURE
GetFrame (name: ARRAY OF CHAR; VAR f: TextFrames.Frame);
VAR x: INTEGER; v: Viewers.Viewer; s: Texts.Scanner;
BEGIN
IF hint # NIL THEN f := hint
ELSE
x := 0; f := NIL;
WHILE x < Display.Width DO
v := Viewers.This(x, 0);
WHILE v.state > 1 DO
IF (v.dsc # NIL) & (v.dsc IS TextFrames.Frame) THEN
Texts.OpenScanner(s, v.dsc(TextFrames.Frame).text, 0); Texts.Scan(s);
IF s.s = name THEN f := v.dsc.next(TextFrames.Frame); RETURN END
END;
v := Viewers.Next(v)
END;
x := x + v.W
END
END GetFrame;
PROCEDURE
GetDsr (f: Display.Frame; pos: LONGINT; fnt: Fonts.Font; VAR dsr: INTEGER);
VAR p: TextFrames.Parc; beg: LONGINT;
BEGIN
IF f = NIL THEN
IF fnt = NIL THEN dsr := 0 ELSE dsr := - fnt.minY END
ELSE
TextFrames.ParcBefore(f(TextFrames.Frame).text, pos, p, beg);
dsr := SHORT(p.dsr DIV TextFrames.Unit)
END GetDsr;
PROCEDURE
CollectMarks (pop: Menu; f0: Display.Frame);
(* Fill popup menu with all mark elements in f0.next.text*)
VAR r: Texts.Reader; s: Texts.Scanner; ch: CHAR; f: TextFrames.Frame; mark: MarkElems.Elem; link: Elem; n: INTEGER;
file: ARRAY 32 OF CHAR;
BEGIN
pop.menu := TextFrames.Text("");
IF (f0.next = NIL) OR ~ (f0.next IS TextFrames.Frame) THEN
Texts.WriteString(w, "link menu not in menu bar of a text viewer"); Texts.WriteLn(w); Texts.WriteLn(w)
ELSE
f := f0.next(TextFrames.Frame); hint := f; GetFileName(f.text, file); n := 0;
Texts.OpenReader(r, f.text, 0); Texts.ReadElem(r);
WHILE ~ r.eot DO
IF r.elem IS MarkElems.Elem THEN
mark := r.elem(MarkElems.Elem);
link := New(file, mark.key);
Texts.WriteElem(w, link); Texts.Write(w, " ");
Texts.OpenScanner(s, f.text, Texts.Pos(r)); Texts.Scan(s);
WHILE ~s.eot & (s.class # Texts.Name) DO Texts.Scan(s) END;
IF ~s.eot THEN Texts.WriteString(w, s.s); Texts.WriteLn(w); INC(n)
END
END;
Texts.ReadElem(r)
END;
IF n = 0 THEN Texts.WriteString(w, "no marks"); Texts.WriteLn(w) END;
IF n <= 1 THEN Texts.WriteLn(w) END;
END;
Texts.Append(pop.menu, w.buf); PopupElems.MeasureMenu(pop)
END CollectMarks;
PROCEDURE
ShowPos (f: TextFrames.Frame; pos: LONGINT);
VAR beg, end, delta: LONGINT;
BEGIN delta := 200;
LOOP beg := f.org; end := TextFrames.Pos(f, f.X + f.W, f.Y);
IF (beg <= pos) & (pos < end) OR (delta = 0) THEN EXIT END;
TextFrames.Show(f, pos - delta); delta := delta DIV 2
END;
TextFrames.SetSelection(f, pos, pos + 1)
END ShowPos;
PROCEDURE
Check (e: Texts.Elem): BOOLEAN;
BEGIN RETURN (e IS MarkElems.Elem) & (e(MarkElems.Elem).key = searchKey)
END Check;
PROCEDURE
FollowLink* (file: ARRAY OF CHAR; key: LONGINT; backF: Display.Frame; backE: Texts.Elem);
VAR v: Viewers.Viewer; menu: TextFrames.Frame; x, y: INTEGER; t: Texts.Text; buf: Texts.Buffer;
mark: Texts.Elem; f: TextFrames.Frame;
BEGIN
GetFrame(file, f);
IF f = NIL THEN
f := TextFrames.NewText(TextFrames.Text(file), 0);
Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y);
IF Files.Old("Edit.Menu.Text") = NIL THEN menu := TextFrames.NewMenu(file, stdMenu)
ELSE menu := TextFrames.NewMenu(file, "");
NEW(t); Texts.Open(t, "Edit.Menu.Text");
NEW(buf); Texts.OpenBuf(buf); Texts.Save(t, 0, t.len, buf); Texts.Append(menu.text, buf)
END;
v := MenuViewers.New(menu, f, TextFrames.menuH, x, y)
END;
searchKey := key;
FoldElems.FindElem(f.text, 0, Check, mark);
IF mark # NIL THEN
ShowPos(f, Texts.ElemPos(mark));
IF backF # NIL THEN MarkElems.backF := backF(TextFrames.Frame) ELSE MarkElems.backF := NIL END;
MarkElems.backE := backE
END FollowLink;
PROCEDURE
Edit (e: Elem);
VAR t: Texts.Text; v: MenuViewers.Viewer; f: Frame; x, y: INTEGER;
BEGIN
t := TextFrames.Text("");
Texts.WriteString(w, e.file); Texts.Write(w, " "); Texts.WriteInt(w, e.key, 0);
Texts.Append(t, w.buf);
NEW(f); f.e := e; TextFrames.Open(f, t, 0);
Oberon.AllocateSystemViewer(0, x, y);
v := MenuViewers.New(
TextFrames.NewMenu("LinkElem", "System.Close LinkElems.Update "),
f, TextFrames.menuH, x, y)
END Edit;
PROCEDURE
Handle* (e: Texts.Elem; VAR m: Texts.ElemMsg);
VAR e1: Elem; x, y, dsr, i: INTEGER; keys: SET; ch: CHAR; follow: FollowMsg;
BEGIN
WITH e: Elem DO
WITH m: Texts.FileMsg DO
IF m.id = Texts.load THEN
i := 0; REPEAT Files.Read(m.r, ch); e.file[i] := ch; INC(i) UNTIL ch = 0X;
Files.ReadLInt(m.r, e.key)
ELSE (*Texts.store*)
i := 0; REPEAT ch := e.file[i]; Files.Write(m.r, ch); INC(i) UNTIL ch = 0X;
Files.WriteLInt(m.r, e.key)
END
| m: Texts.CopyMsg DO
IF m.e = NIL THEN NEW(e1); m.e := e1 ELSE e1 := m.e(Elem) END;
Texts.CopyElem(e, e1); COPY(e.file, e1.file); e1.key := e.key
| m: Texts.IdentifyMsg DO
m.mod := "LinkElems"; m.proc := "Alloc"
| m: TextFrames.DisplayMsg DO
IF ~m.prepare THEN
GetDsr(m.frame, m.pos, m.fnt, dsr);
Display.CopyPattern(Display.white, icon, m.X0, m.Y0+dsr, Display.paint)
END
| m: TextPrinter.PrintMsg DO
IF m.prepare THEN e.W := 1 ELSE e.W := 10 * pixel END
| m: TextFrames.TrackMsg DO
IF middle IN m.keys THEN
IF m.frame # NIL THEN
GetDsr(m.frame, m.pos, m.fnt, dsr);
Display.CopyPattern(Display.white, icon, m.X0, m.Y0+dsr, Display.invert);
Display.CopyPattern(Display.white, invIcon, m.X0, m.Y0+dsr, Display.invert);
REPEAT Input.Mouse(keys, x, y); m.keys := m.keys + keys;
Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, x, y)
UNTIL keys = {};
Display.CopyPattern(Display.white, invIcon, m.X0, m.Y0+dsr, Display.invert);
Display.CopyPattern(Display.white, icon, m.X0, m.Y0+dsr, Display.invert)
END;
IF m.keys = {middle} THEN follow.f := m.frame; e.handle(e, follow)
ELSIF m.keys = {middle, right} THEN Edit(e)
END
END
| m: FollowMsg DO
FollowLink(e.file, e.key, m.f, e)
ELSE
END
END Handle;
PROCEDURE
HandleMenu* (e: Texts.Elem; VAR m: Texts.ElemMsg);
VAR e1: Menu;
BEGIN
WITH e: Menu DO
WITH
m: Texts.IdentifyMsg DO
m.mod := "LinkElems"; m.proc := "AllocMenu"
| m: Texts.CopyMsg DO
NEW(e1); m.e := e1; PopupElems.Handle(e, m)
| m: TextFrames.DisplayMsg DO
IF m.prepare THEN
e.W := 13 * pixel; e.H := LONG(TextFrames.menuH-1) * pixel;
ELSE e.name := ""; PopupElems.Handle(e, m);
Display.CopyPattern(Display.white, icon, m.X0+2, m.Y0+3, Display.paint)
END
| m: TextFrames.TrackMsg DO
IF middle IN m.keys THEN
CollectMarks(e, m.frame); PopupElems.Handle(e, m); hint := NIL
END
ELSE PopupElems.Handle(e, m)
END
END HandleMenu;
PROCEDURE
Alloc*;
VAR e: Elem;
BEGIN
NEW(e); e.handle := Handle; Texts.new := e
END Alloc;
PROCEDURE
AllocMenu*;
VAR e: Menu;
BEGIN
NEW(e); e.handle := HandleMenu; Texts.new := e
END AllocMenu;
PROCEDURE
New* (file: ARRAY OF CHAR; key: LONGINT): Elem;
VAR e: Elem;
BEGIN
NEW(e); e.W := 10 * pixel; e.H := 11 * pixel; e.handle := Handle; COPY(file, e.file); e.key := key;
RETURN e
END New;
PROCEDURE
Insert*;
VAR link: Elem; mark: MarkElems.Elem; fromT, toT: Texts.Text; toPos, end, time: LONGINT;
r: Texts.Reader; ch: CHAR; m: TextFrames.InsertElemMsg; f: TextFrames.Frame;
BEGIN
f := Oberon.FocusViewer.dsc(TextFrames.Frame);
IF f.hasCar THEN fromT := f.text ELSE fromT := f.next(TextFrames.Frame).text END;
Oberon.GetSelection(toT, toPos, end, time);
IF time >= 0 THEN
link := New("", 0); GetFileName(toT, link.file);
Texts.OpenReader(r, toT, toPos); Texts.Read(r, ch);
m.e := link; Viewers.Broadcast(m);
IF (ch = Texts.ElemChar) & (r.elem IS MarkElems.Elem) THEN
link.key := r.elem(MarkElems.Elem).key
ELSE
IF (fromT = toT) & (Texts.ElemPos(link) <= toPos) THEN INC(toPos) END;
mark := MarkElems.New(); link.key := mark.key;
Texts.WriteElem(w, mark); Texts.Insert(toT, toPos, w.buf)
END
END Insert;
PROCEDURE
InsertMenu*;
VAR e: Menu; insert: TextFrames.InsertElemMsg;
BEGIN
NEW(e); e.handle := HandleMenu; e.name := ""; e.menu := TextFrames.Text(""); e.small := TRUE;
PopupElems.MeasureMenu(e);
insert.e := e; Viewers.Broadcast(insert)
END InsertMenu;
PROCEDURE
Update*;
VAR f: Frame; t: Texts.Text; s: Texts.Scanner; r: Texts.Reader; ch: CHAR;
BEGIN
IF (Oberon.Par.frame = Oberon.Par.vwr.dsc) & (Oberon.Par.frame.next IS Frame) THEN
f := Oberon.Par.frame.next(Frame);
Texts.OpenScanner(s, f.text, 0); Texts.Scan(s);
IF s.class = Texts.Name THEN
COPY(s.s, f.e.file); Texts.Scan(s);
IF s.class = Texts.Int THEN
f.e.key := s.i;
t := Oberon.Par.frame(TextFrames.Frame).text;
Texts.OpenReader(r, t, t.len-1); Texts.Read(r, ch);
IF ch = "!" THEN Texts.Delete(t, t.len-1, t.len) END
END
END
END Update;
PROCEDURE
InitIcon;
VAR line: ARRAY 9 OF SET;
BEGIN
line[8] := {4};
line[7] := {3, 5};
line[6] := {2, 6};
line[5] := {1..3, 5..7};
line[4] := {3, 5};
line[3] := {3, 5};
line[2] := {3, 5};
line[1] := {3..5};
icon := Display.NewPattern(line, 9, 8);
line[8] := {4};
line[7] := {3..5};
line[6] := {2..6};
line[5] := {1..7};
line[4] := {3..5};
line[3] := {3..5};
line[2] := {3..5};
line[1] := {3..5};
invIcon := Display.NewPattern(line, 9, 8)
END InitIcon;
BEGIN
Texts.OpenWriter(w);
InitIcon;
hint := NIL
END LinkElems.